package com.dyp.argumentvalidation.ctr;

import com.dyp.argumentvalidation.model.Book;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.hibernate.validator.constraints.Length;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


//使用RestController可以省略在方法上的@ResponseBody注解
@RestController
@RequestMapping(value = "/mvc")
@Tag(name = "api for mvc")
@Validated //为了解决路径参数和RequestParam的请求验证
public class RestfulCtr {

    // 验证不过抛出异常MethodArgumentNotValidException，可以交给全局异处理器统一处理
    @PostMapping("/validated")
    public Book createBook11(@RequestBody @Validated  Book book){
        System.out.println(book.toString());
        return book;
    }
    // 有BindingResult，Validated没有验证通过的时候优先传入该方法让用户解决，并不会抛出异常
    @PostMapping("/validated/binding")
    public Book createBook12(@RequestBody @Validated Book book, BindingResult bindingResult){
        if(bindingResult.hasErrors())
        {
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                System.out.println(fieldError.toString());
                book.setName(fieldError.toString());
            }
        }
        System.out.println(book.toString());
        return book;
    }

    //这个方法中，当出现Book没有验证通过的时候，是不会传入BindingResult，而是直接抛出异常ConstraintViolationException
    @PostMapping("/valid/binding")
    public Book createBook22(@RequestBody @Valid Book book, BindingResult bindingResult){
        if(bindingResult.hasErrors())
        {
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                System.out.println(fieldError.toString());
                book.setName(fieldError.toString());
            }
        }
        System.out.println(book.toString());
        return book;
    }

    // 验证失败抛出 MethodArgumentNotValidException:
    @PostMapping("/valid")
    public Book createBook21(@RequestBody @Valid Book book){
        System.out.println(book.toString());
        return book;
    }

    // 验证不通过会抛出 ConstraintViolationException
    @GetMapping(value = "path/{id}")
    public String pathParamAndRequestParam(@PathVariable(name = "id")
                             @Length(min=2, max = 6,message = "2< id的长度 <6") String id,
            @RequestParam(name = "name", required = false)
                         @Length(min=2, max = 6,message = "2< name的长度 <6") String name)
    {
        return "hi " + name  ;
    }

    /**
     * 下面的写法是不允许的。报错：
     * An Errors/BindingResult argument is expected to be declared immediately after the model attribute,
     * the @RequestBody or the @RequestPart arguments to which they apply
     * @param name
     * @return
     */
//    @GetMapping(value = "hello/{id}/binding")
//    public String sayHi4(@PathVariable(name = "id")
//                         @Length(min=2, max = 6,message = "2< id的长度 <6") String id,
//                         @RequestParam(name = "name", required = false)
//                         @Length(min=2, max = 6,message = "2< name的长度 <6") String name, BindingResult bindingResult)
//    {
//        if(bindingResult.hasErrors())
//        {
//            for (FieldError fieldError : bindingResult.getFieldErrors()) {
//                System.out.println(fieldError.toString());
//            }
//        }
//        return "hi " + name  ;
//    }

    // 验证失败抛出ConstraintViolationException
    @GetMapping(value = "request")
    public String requestParam(
                         @RequestParam(name = "name", required = true)
                         @Length(min=2, max = 6,message = "2< id的长度 <6") String name)
    {
        return "hi " + name  ;
    }
}
